package com.tianruan.dc.modules.sys.user.security.provider;

import com.tianruan.dc.common.auth.MAuthenticationUser;
import com.tianruan.dc.common.user.MUserDetailService;
import com.tianruan.dc.modules.sys.user.entity.WXResponse;
import com.tianruan.dc.modules.sys.user.entity.db.PermissionDO;
import com.tianruan.dc.modules.sys.user.entity.dto.UserDTO;
import com.tianruan.dc.modules.sys.user.security.authenticationToken.WXMiniAuthenticationToken;
import com.tianruan.dc.modules.sys.user.service.IBindWXService;
import com.tianruan.dc.modules.sys.user.service.IUserService;
import com.tianruan.dc.modules.sys.user.utils.WXUtils;
import com.tianruan.dc.modules.userinfo.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @PS
 */
@Component
public class WXMiniAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private MUserDetailService mUserDetailService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private WXUtils wxUtils;
    @Autowired
    private IUserService userService;
    @Autowired
    private IBindWXService bindWXService;
    @Autowired
    private AdminService adminService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 手机 号码
        String code = (String) authentication.getCredentials();

        // 获取当前微信小程序登录code对应的openid
        WXResponse wxResponse = wxUtils.code2Session(code);
        if (wxResponse == null || wxResponse.getOpenid() == null) {
            throw new BadCredentialsException("登录失败！");
        }

        String openid = wxResponse.getOpenid();
        String sessionKey = wxResponse.getSessionKey();


        // 查询数据库，看是否存在与之相关联的用户ID
        String userId = bindWXService.selectBind(openid);
        if (userId == null) {
            throw new UsernameNotFoundException("没有绑定用户，请先去注册");
//            // 如果不存在相关联的用户ID，则表示用户尚未绑定，或者绑定关系已经失效，需要进行绑定操作
//
//            // 绑定微信用户和现有用户ID
//            bindWXService.bind(userId, openid) ;
//
//            // 绑定后再次查询用户ID
//            userId =  bindWXService.selectBind(openid);
//            if (userId == null) {
//                throw new UsernameNotFoundException("绑定失败，请联系管理员！");
//            }
        }

        //根据用户ID查询用户名
        String username = adminService.getById(userId).getUsername();
        if (username == null){
            throw new UsernameNotFoundException("用户不存在");
        }

        // 获取用户为该openid的用户
        UserDTO userDTO = userService.getUserPermissionByNo(username);

//        if (userDTO == null) {
//            // 没有用户就创建
//
//            userDTO = new UserDTO();
//            userDTO.setCompanyId("1");
//            userDTO.setOfficeId("100");
//            userDTO.setUsername(openid);
//            userDTO.setNo(openid);
//            userDTO.setPassword(openid + "1");
//            userDTO.setName("u_" + new Date().getTime());
//            userDTO.setType("1");
//            userDTO.preInsertAdmin();
//
//            // 微信登录默认为访客
//            List<String> roleIds = Arrays.asList("6");
//            userDTO.setRoleIds(roleIds);
//
//            userService.insertUser(userDTO);
//
//            userDTO = userService.getUserPermissionByNo(openid);
//        }





        // 登录用户信息
        String[] permissionList = userDTO.getPermissionList().stream().map(PermissionDO::getPermission).toArray(String[]::new);
        MAuthenticationUser userDetails = new MAuthenticationUser(userDTO.getId(),
                userDTO.getOfficeId(),
                userDTO.getName(),
                userDTO.getUsername(),
                userDTO.getPassword(),
                userDTO.getNo(),
                userDTO.getPhone(),
                userDTO.getEmail(),
                userDTO.getSex(),
                AuthorityUtils.createAuthorityList(permissionList));

        return new UsernamePasswordAuthenticationToken(userDetails, "123456", userDetails.getAuthorities());
    }

    /**
     * AuthenticationManager 本身不包含认证逻辑，其核心是用来管理所有的 AuthenticationProvider，通过交由合适的 AuthenticationProvider 来实现认证。
     * ProviderManager 是AuthenticationProvider的实现类
     * AuthenticationManager获取所有AuthenticationProvider的实现
     * 通过该方法判断是否支持当前方式的认证
     * 这里支持验证UsernamePasswordAuthenticationToken
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(WXMiniAuthenticationToken.class);
    }

}
